#ifndef PFILEINFO_H_
#define PFILEINFO_H_

#include <fstream>
#include <string>
#include <vector>
#include <iterator>
#include <ios>
#include <fstream>
#include <sstream>
#include <boost/filesystem/operations.hpp> //for file_size method
#include "DataFileException.h"
#include "PConvertor.h"
#include "Tools.h"

namespace PComunicator
{

//! Definicia byte ako datoveho typu 
/*!
 	byte predstavuje datovy typ ktory je reprezentovany ako unsigned char
*/
typedef unsigned char byte;


/*! 
 * PFileInfo trieda
 * 
 * Trieda ktora sluzi na uchovavanie nejake suboru v pameti a naviac uchovava dodatocne informacie o subore
 * Z triedy PFileInfo sa daju ziskat informacie ako typ suboru,velkost atd... 
 */

class PFileInfo
{
	public:
		//! Constructor
		/*!
			\param theFullFilePath absolutna cesta k suboru pre ktory sa ma vytvorit objekt
		*/
		PFileInfo(std::string theFullFilePath);

		//! Constructor na zostavenie objektu z formatovaneho pola byte
		/*!
			\param formatovane pole byte (unsigned char)
		*/
		PFileInfo(const std::vector<byte> &theEncodedFileInfo);

		//! Constructor na zostavenie objektu z vstupneho stream (istream)
		/*!
			\param theFullFileName nazov suboru
			\param smernik na objekt typu std::istream
		*/
		PFileInfo(std::string theFullFileName,std::istream *pIstream);
		
		//! Copy Constructor
		/*!
		*/
		PFileInfo(const PFileInfo& fileInfo);

		//! Assign operator overloading
		/*!
		*/
		PFileInfo& operator=(const PFileInfo& fileInfo);

		//! Destructor
		/*!
			Default
		*/
		~PFileInfo(void);

		//! Ziska velkost suboru
		/*!
			\return navrati velkost suboru
		*/
		unsigned long long GetSize();

		//! Ziska nazov suboru
		/*!
			\return nazov suboru bez suborovej pripony
		*/
		std::string GetName();

		//! Ziska nazov suboru
		/*!
			\return nazov suboru aj s suborovou priponou
		*/
		std::string GetFullName();

		//! Ziska uplnu cestu k suboru
		/*!
			\return uplna cesta k suboru
		*/
		std::string GetFullPath();

		//! Ziska typ suboru
		/*
			\return navrati typ suboru v pripade ak nejaky existuje
		*/
		std::string GetFileType();

		//! Ziska suboru
		/*
			\return navrati samotny subor
		*/
		std::vector<byte> GetFile();

		//! Ziska stream na subor
		/*
			\param stream ktory sa pouzije na citanie suboru
		*/
		void GetFileStream(std::istream **ptheStream);

		//! Zapise celi objekt do pola byte (unsigned char)
		/*
			Samotny objekt sa zapise do pola byte, ktory ma svoj presne definovany format.
			Tento format ma nasledujuci tvar:
			
			4byte = [dlzka_nazvu] = dlzka plneho nazvu suboru
			[dlzka_nazvu]*byte = [nazov_suboru] = plny nazov suboru
			4byte = [dlzka_suboru] = dlzka samotneho suboru
			[dlza_suboru]*byte = [subor] = samotny subor 
			
			Pretoze dlzka suboru sa koduje do 4 byte, vznika limit na maximalnu velkost
			subory ktory sa da kodovat do pola byte teda sa moze posielat pomocou
			PComunicator cez net. Tento limit predstavuje maximalnu velkost suboru: 
			na sizeof(unsigned int) teda 4294967296. 

			\return navrati formatovane pole byte ,ktore obsahuje celi objekt
		*/
		std::vector<byte> FormatToArray();

		//! Zapise subor na urcene miesto na lokalnom disku
		/*
			\param plna cesta kam sa subor ma zapisat 
		*/
		bool Save(std::string theFullPath);

	private:
		void ReadFile();
		void GetInfo(std::string theFile);
		void GetInfo(std::string theFullName,unsigned long theSize);
		void Swap(PFileInfo& fileInfo);
		std::vector<byte> myFile;
		unsigned long long mySize;
		std::string myFileType;
		std::string myName;
		std::string myFullName;
		std::string myFullPath;
		std::istringstream *iss;
};

}
#endif
